﻿using System;
using System.Windows.Forms;
using System.Drawing;
using System.Drawing.Imaging;

namespace TutorialDoubleBuffering
{
	class TetrisGame : Game
	{
		private enum InputEvent
		{
			Key_None,
			Key_Left,
			Key_Right,
			Key_Up,
			Key_Down,
		};

		private const int BoardWidth = 9;
		private const int BoardHeight = 19;

		private byte[][] gameBoard = null;

		private Bitmap cellImage = null;


		private bool isMoving = false;
		private int dropEventTime = 0;
		private int dropIntervalTime = 1000;
		private int moveElapsedTime = 0;
		private int moveIntervalTime = 100;


		private InputEvent keyEvent = InputEvent.Key_None;


		private int prevPosX = 0;
		private int prevPosY = 0;
		private int curPosX = 0;
		private int curPosY = 0;
		

		public override bool Init()
		{
			Size bufferdGraphicSize = BufferedGraphicsManager.Current.MaximumBuffer;

			this.cellImage = new Bitmap("Resource/Cell.bmp");

			// initialize board
			gameBoard = new byte[BoardWidth][];
			for (int x = 0; x < BoardWidth; ++x)
				gameBoard[x] = new byte[BoardHeight];

			this.prevPosX = this.curPosX;
			this.prevPosY = this.curPosY;

			return true;
		}

		[System.Runtime.InteropServices.DllImport("user32.dll")]
		private static extern int GetAsyncKeyState(int vKey);

		public override void Input(int elapsedTime)
		{
			// 키 이벤트 체크
			if ((GetAsyncKeyState(0x25) & 0x8001) != 0)
				this.keyEvent = InputEvent.Key_Left;
			else if ((GetAsyncKeyState(0x27) & 0x8001) != 0)
				this.keyEvent = InputEvent.Key_Right;
			else if ((GetAsyncKeyState(0x28) & 0x8001) != 0)
				this.keyEvent = InputEvent.Key_Down;
		}

		public override void UpdateFrame(int elapsedTime)
		{
			// 키 이벤트 처리
			switch (this.keyEvent)
			{
				case InputEvent.Key_Left:
					if (!this.isMoving)
					{
						OnKeyEventMoveLeft(elapsedTime);
						this.isMoving = true;
					}
					CheckMoveTime(elapsedTime);
					break;
				case InputEvent.Key_Right:
					if (!this.isMoving)
					{
						OnKeyEventMoveRight(elapsedTime);
						this.isMoving = true;
					}
					CheckMoveTime(elapsedTime);
					break;
				case InputEvent.Key_Down:
					if (!this.isMoving)
					{
						OnKeyEventMoveDown(elapsedTime);
						this.isMoving = true;
					}
					CheckMoveTime(elapsedTime);
					break;
			}

			// 매 시간 처리
			if (this.dropEventTime > this.dropIntervalTime)
			{
				OnTimeMoveDown();
				
				this.dropEventTime = 0;
			}
			else
				this.dropEventTime += elapsedTime;
		}

		public override void RenderFrame(Graphics g, int elapsedTime)
		{
			for (int x = 0; x < this.gameBoard.Length; ++x)
			{
				for (int y = 0; y < this.gameBoard[x].Length; ++y)
				{
					if (this.gameBoard[x][y] == 1)
					{
						g.DrawImage(this.cellImage, this.cellImage.Width * x, this.cellImage.Height * y);
					}
				}
			}

			// text for debug
			g.DrawString(
				this.curPosX.ToString() + "/" + this.curPosY.ToString(),
				new Font("굴림체", 10),
				Brushes.Red,
				new PointF(10, 10));

			g.DrawString(
				this.isMoving.ToString() + "/" + this.keyEvent.ToString(),
				new Font("굴림체", 10),
				Brushes.Red,
				new PointF(10, 20));
		}

		private void CheckMoveTime(int elapsedTime)
		{
			if (this.moveElapsedTime > this.moveIntervalTime)
			{
				this.isMoving = false;
				this.keyEvent = InputEvent.Key_None;
				this.moveElapsedTime = 0;
			}
			else
				this.moveElapsedTime += elapsedTime;
		}

		private void OnTimeMoveDown()
		{
			// 바닥 충돌 체크
			if (this.curPosY >= BoardHeight)
				this.curPosY = 0;
			else
				this.curPosY++;
		}
		
		private void OnKeyEventMoveDown(int elapsedTime)
		{
			this.curPosY++;
		}

		private void OnKeyEventMoveLeft(int elapsedTime)
		{
			this.curPosX--;
		}

		private void OnKeyEventMoveRight(int elapsedTime)
		{
			this.curPosX++;
		}

		private void AddNewBlock()
		{
		}

		private void CheckLine()
		{
		}
	}
}
